/*
 *	Copyright (C) 2008 CRIMERE
 *	Copyright (C) 2008 Jean-Marc Mercier
 *	
 *	This file is part of OTS (optimally transported schemes), an open-source library
 *	dedicated to scientific computing. http://code.google.com/p/optimally-transported-schemes/
 *
 *	CRIMERE makes no representations about the suitability of this
 *	software for any purpose. It is provided "as is" without express or
 *	implied warranty.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
#if !defined(_IOFacilities_)
#define _IOFacilities_

#include <set>
#include <list>
#include <map>
#include <vector>
#include <iostream>
#include <sstream>
#include <src/miscellaneous/OS_basic.h>
#include <boost/multi_index_container.hpp>


template <class V >
std::istream &operator>>(std::istream &in, std::list<V> &v) {
    do {
      char buf[10000];
      in.getline(buf, 10000);
      if (!in || buf[0]=='\0' || buf[0]=='#') break;
      std::istringstream iss(buf);
      V d; 
      iss >> d;
      if (!iss) {
	std::cerr << "ERROR reading object from line " << buf << std::endl;
      } else {
	v.push_back(d);
      }
    } while (true);
    return in;
};


template <class V >
std::ostream &operator<<(std::ostream &out, const std::list<V> &v) {
	std::list<V>::const_iterator  begin = v.begin() , end = v.end();
	out << "[";
	for (;begin != end;) {
		out << *begin;
		if (begin++ != end)
			out << ",";
	};
	out << "]";
  return out;
};


template <class V1,class V2 >
std::ostream &operator<<(std::ostream &out, const std::pair<typename V1,typename V2> &pair_) {
	out << "(" << pair_.first << "," << pair_.second << ")" ;
  return out;
};


template <class V, class V_ >
std::ostream &operator<<(std::ostream &out, const std::set<V,V_> &v) {
	std::set<V,V_>::const_iterator  begin = v.begin() , end = v.end();
	for (;begin != end; ++begin) {
		out << *begin;
		std::set<V,V_>::const_iterator it = begin;
		it++;
		if (it != end) out << ",";
	};
  return out;
};


template<class V>
std::istream &operator>>(std::istream &in, std::vector<V> &v) {
    do {
      char buf[10000];
      in.getline(buf, 10000);
      if (!in || buf[0]=='\0' || buf[0]=='#') break;
      std::istringstream iss(buf);
      V d; 
      iss >> d;
      if (!iss) {
	std::cerr << "ERROR reading object from line " << buf << std::endl;
      } else {
	v.push_back(d);
      }
    } while (true);
    return in;
};


template <class V >
std::ostream &operator<<(std::ostream &out, const std::vector<V> &v) {
	std::vector<V>::const_iterator  begin = v.begin() , end = v.end();
	for (;begin != end; ++begin)
		out << *begin << std::endl;
  return out;
};
template <class Key, class V >
std::ostream &operator<<(std::ostream &out, const std::map<Key,V> &v) {
	std::map<Key,V>::const_iterator  begin = v.begin() , end = v.end();
	for (;begin != end; ++begin)
		out << *begin << std::endl;
  return out;
};


std::istream &operator>>(std::istream &in, std::vector<OS_double> & t);
std::ostream& operator<< (std::ostream& o, const std::vector<OS_double> & t);

#endif //IOFacilities